#include "ImgPre.h"

namespace fs = boost::filesystem;

namespace ImgPre 
{
	/*! Checks a given directory for all .PNGs and .JPEGs and stores them in the vector
	* @param folderPath The directory to be checked
	* @param loadedFilePaths Pointer to the vector, where the paths are to be stored
	*/
	void loadImageFilePaths(string folderPath, vector<string> *loadedFilePaths)
	{
		fs::path someDir(folderPath);
		fs::directory_iterator end_iter;
		if (fs::exists(someDir) && fs::is_directory(someDir))
		{
			cout <<"Loading Image-Paths" <<endl;
			for(fs::directory_iterator dir_iter(someDir); dir_iter != end_iter; ++dir_iter)
			{
				if(dir_iter->path().extension() == ".png" || dir_iter->path().extension() == ".jpg")
				{
					(*loadedFilePaths).push_back(dir_iter->path().string());
				}
				else
				{
					cout<<dir_iter->path().string()<<" Not a .png file"<<endl;
				}
			}
		}
		else
		{
			cout<<"Not a valid path" << endl;
		}
	}

	/*! Creates a OpLib::WorkingObject out of the file specified. Loads the image and stores the name
	* @param filePath The path to the file, which is to be loaded
	* @return A OpLib::WorkingObject* containing the image and name
	*/

	WorkingObject* loadImageFromFile(string filePath){
		Mat image = imread(filePath, CV_LOAD_IMAGE_COLOR);

		WorkingObject* object = new WorkingObject();
		object->source_image = image;
		object->filename = filePath;

		return object;
	}


	/*! Takes an image and creates all the scaled down versions of it. Every new octave the
	* image is resized from source, else it is resized from the image one step earlier 
	* @param obj working object
	*/
	void addScaledImagesToWorkingObject(WorkingObject *obj)
	{
		//Size of the sliding window
		int minWidth = 64;
		int minHeight = 128;

		float* scale_factors = computeScaleFactors();
		int length = 7*LAMBDA;

		//Output
		Mat tmp;
		Mat input_image=obj->source_image;

		for(int i=1; i <= length; i++)
		{
			if(input_image.cols*(1.0/ scale_factors[i]) < minWidth || input_image.rows*(1.0/ scale_factors[i]) < minHeight)
			{
				return;
			}
			//Downscaled image
			Mat img = Mat((int)(input_image.rows*(1.0/ scale_factors[i])), (int)(input_image.cols*(1.0/ scale_factors[i])), input_image.type());

			if(i == 1 || i%LAMBDA == 0)
			//New octave => resize image from source
			{
				resize(input_image, img, Size(img.cols, img.rows), 0, 0, 1);
			}
			else
			//Old octave => resize image from one step earlier
			{
				resize(tmp, img, Size(img.cols, img.rows), 0, 0, 1);
			}
			tmp = img;
			WorkImage * w_img= new WorkImage();
			w_img->scaled_img = img;
			w_img->scale_factor = 1.f/ scale_factors[i];
			obj->addLowerElement(w_img);
		}
	}
	
	/** Creates the scale factors neccesary to scale all the images. 
	* @return An array containing all the factors
	*/
	float* computeScaleFactors()
	{
		float* array = 0;

		if(LAMBDA < 1)
		{
			array[0] = 1.0;
			return array;
		}

		const int max = 7*LAMBDA;
		array = new float [max];

		float scale = (float)pow(2.0, 1.0/LAMBDA);

		array[0] = 1.0;
		for(int i=0; i < 7; i++)
		{
			for(int j=0; j <LAMBDA; j++)
			{
				array[i*LAMBDA + j +1] = (float) array[i*LAMBDA + j]*scale;
			}
		}

		return array;
	}
}